﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LDCRNewEdit.Model;
using System.IO;
using LDCRNewEdit.Utils;
using System.Drawing;
using System.Drawing.Imaging;

namespace LDCRNewEdit.Services
{
    public class SceneMapService
    {
        /// <summary>
        /// 保存场景地面图
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="list"></param>
        public static void SaveGroundMap(string filename, List<SceneGroundLv> list)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Create))
            {

                //个数
                fs.Write(Tools.ShortToBytes((short)list.Count), 0, 2);

                foreach (SceneGroundLv sg in list)
                {

                    fs.Write(Tools.ShortToBytes((short)sg.X), 0, 2);//X
                    fs.Write(Tools.ShortToBytes((short)sg.Y), 0, 2);//Y
                    fs.Write(Tools.ShortToBytes((short)sg.Image.Width), 0, 2);//W
                    fs.Write(Tools.ShortToBytes((short)sg.Image.Height), 0, 2);//H
                    

                    byte[] bytes = ImageUtil.ImageToBytes(sg.Image, ImageFormat.Jpeg);

                    //先存长度，再存内容
                    fs.Write(Tools.IntToBytes(bytes.Length), 0, 4);
                    fs.Write(bytes, 0, bytes.Length);

                    fs.Flush();
                }
            }
        }

        /// <summary>
        /// 加载场景地面图
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static List<SceneGroundLv> LoadGroundMap(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                List<SceneGroundLv> list = new List<SceneGroundLv>();

                byte[] buf = new byte[fs.Length];
                fs.Read(buf, 0, buf.Length);

                int off = 0;
                short num = Tools.BytesToShort(buf, 0);
                off += 2;

                for (int i = 0; i < num; i++)
                {
                    SceneGroundLv sg = new SceneGroundLv();
                    sg.X = Tools.BytesToShort(buf, off); off += 2;
                    sg.Y = Tools.BytesToShort(buf, off); off += 2;
                    sg.W = Tools.BytesToShort(buf, off); off += 2;
                    sg.H = Tools.BytesToShort(buf, off); off += 2;

                    int size = Tools.BytesToInt(buf, off); off += 4;
                    sg.Image = ImageUtil.BytesToImage(buf, off, size);

                    off += size;

                    list.Add(sg);
                }

                return list;
            }
        }


        /// <summary>
        /// 保存场景
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="map"></param>
        public static void SaveSceneMap(string filename, SceneMap map)
        {
            List<byte[]> list = new List<byte[]>();
            list.Add(Tools.StringToBytes(map.Name, 20, true));  //场景名称

            list.Add(Tools.ShortToBytes(map.MapWidth));      //场景宽
            list.Add(Tools.ShortToBytes(map.MapHeight));     //场景高
            list.Add(Tools.ShortToBytes(map.XOff));        //图片默认偏移X
            list.Add(Tools.ShortToBytes(map.YOff));        //图片默认偏移Y
            list.Add(Tools.ShortToBytes(map.MaxWidth));        //场景最大可见范围
            list.Add(Tools.ShortToBytes(map.MaxHeight));        //场景最大可见范围

            list.Add(Tools.StringToBytes(map.GroundPath.Replace("\\","/"), 64, true));  //场景地面路径

            List<SceneBuildLv> buildList = map.BuilList;
            buildList.Sort();

            list.Add(Tools.ShortToBytes((short)buildList.Count));
            foreach (SceneBuildLv sl in buildList)
            {
                list.Add(new byte[] { sl.Level });     //层次
                list.Add(new byte[] { sl.PlayMode });     //播放方式
                list.Add(new byte[] { sl.FrameNum });     //帧数
                list.Add(Tools.ShortToBytes(sl.FrameDelay));      //延迟毫秒数
                list.Add(Tools.ShortToBytes(sl.KeyPointX));        //图片重心点X
                list.Add(Tools.ShortToBytes(sl.KeyPointY));        //图片重心点Y
                list.Add(Tools.ShortToBytes(sl.X));        //图片默认位置X
                list.Add(Tools.ShortToBytes(sl.Y));        //图片默认位置Y
                list.Add(Tools.ShortToBytes(sl.W));        //图片宽度
                list.Add(Tools.ShortToBytes(sl.H));        //图片高度
                list.Add(Tools.StringToBytes(sl.Path.Replace("\\", "/"), 64, true));  //建筑图片路径
            }


            //障碍点
            list.Add(Tools.ShortToBytes((short)map.BlockSet.Count));
            foreach (Point p in map.BlockSet)
            {
                list.Add(Tools.ShortToBytes((short)p.X));     //障碍点X
                list.Add(Tools.ShortToBytes((short)p.Y));     //障碍点Y
            }

            
            //保存
            using (FileStream fs = new FileStream(filename, FileMode.Create))
            {
                //数据
                foreach (byte[] bytes in list)
                {
                    fs.Write(bytes, 0, bytes.Length);
                }

            }
        }


        /// <summary>
        /// 读取场景数据
        /// </summary>
        /// <param name="filename"></param>
        public static SceneMap LoadSceneMap(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                SceneMap map = new SceneMap();

                byte[] buf = new byte[fs.Length];
                fs.Read(buf, 0, buf.Length);

                int off = 0;

                map.Name = Tools.BytesToString(buf, 20, true, off); off += 20;
                map.MapWidth = Tools.BytesToShort(buf, off); off += 2;
                map.MapHeight = Tools.BytesToShort(buf, off); off += 2;
                map.XOff = Tools.BytesToShort(buf, off); off += 2;
                map.YOff = Tools.BytesToShort(buf, off); off += 2;
                map.MaxWidth = Tools.BytesToShort(buf, off); off += 2;
                map.MaxHeight = Tools.BytesToShort(buf, off); off += 2;
                map.GroundPath = Tools.BytesToString(buf, 64, true, off); off += 64;

                //读取建筑部分
                int bnum = Tools.BytesToShort(buf, off); off += 2;
                for (int i = 0; i < bnum; i++)
                {
                    SceneBuildLv build = new SceneBuildLv();
                    build.Level = buf[off]; off += 1;
                    build.PlayMode = buf[off]; off += 1;
                    build.FrameNum = buf[off]; off += 1;

                    build.FrameDelay = Tools.BytesToShort(buf, off); off += 2;
                    build.KeyPointX = Tools.BytesToShort(buf, off); off += 2;
                    build.KeyPointY = Tools.BytesToShort(buf, off); off += 2;
                    build.X = Tools.BytesToShort(buf, off); off += 2;
                    build.Y = Tools.BytesToShort(buf, off); off += 2;
                    build.W = Tools.BytesToShort(buf, off); off += 2;
                    build.H = Tools.BytesToShort(buf, off); off += 2;
                    build.Path = Tools.BytesToString(buf, 64, true, off); off += 64;

                    //加载IMAGE
                    build.Image = Image.FromFile(Resources.GamePath+build.Path);

                    map.BuilList.Add(build);
                }

                //读取障碍物点
                int cnum = Tools.BytesToShort(buf, off); off += 2;
                for (int i = 0; i < cnum; i++)
                {
                    Point p = new Point();
                    p.X = Tools.BytesToShort(buf, off); off += 2;
                    p.Y = Tools.BytesToShort(buf, off); off += 2;

                    map.BlockSet.Add(p);
                }

                return map;

            }

           
        }
        
        /// <summary>
        /// 保存场景数据
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="?"></param>
        public static void SaveSceneData(string filename, SceneData sceneData)
        {
            List<byte[]> list = new List<byte[]>();
            list.Add(Tools.StringToBytes(sceneData.SceneMapPath, 64, true)); //场景文件路径
            list.Add(new byte[] { sceneData.OpenFlag });     //打开标志

            //NPC
            list.Add(Tools.ShortToBytes((short)sceneData.SceneNPCList.Count));  //个数
            foreach (Point p in sceneData.SceneNPCList.Keys)
            {
                SceneNPC npc = sceneData.SceneNPCList[p];
                list.Add(new byte[] { npc.EventType });     //事件类型
                list.Add(Tools.ShortToBytes(npc.X));      //x
                list.Add(Tools.ShortToBytes(npc.Y));      //Y

                list.Add(new byte[] { (byte)npc.EventList.Count }); //事件个数
                for (int n = npc.EventList.Count - 1; n >= 0; n--)
                {
                    list.Add(Tools.StringToBytes(npc.EventList[n].ID, 64, true));
                    list.Add(new byte[] { (byte)(npc.EventList.Count - n) });    //事件优先级
                }
                list.Add(Tools.ShortToBytes((short)npc.EID));      //事件者编号
                list.Add(new byte[] { npc.Direction });     //方向
                list.Add(Tools.ShortToBytes((short)npc.Voice)); //对话音效
            }

            //跳转场景
            list.Add(Tools.ShortToBytes((short)sceneData.SceneJumpList.Count));
            foreach (Point p in sceneData.SceneJumpList.Keys)
            {
                SceneJump js = sceneData.SceneJumpList[p];
                list.Add(Tools.ShortToBytes((short)js.X));     //X
                list.Add(Tools.ShortToBytes((short)js.Y));     //Y
                list.Add(Tools.StringToBytes(js.SceneID, 32, true));    //场景ID
                list.Add(Tools.ShortToBytes((short)js.ToX));     //目标X
                list.Add(Tools.ShortToBytes((short)js.ToY));     //目标Y

            }

            //保存
            using (FileStream fs = new FileStream(filename, FileMode.Create))
            {
                //数据
                foreach (byte[] bytes in list)
                {
                    fs.Write(bytes, 0, bytes.Length);
                }

            }
        }

        /// <summary>
        /// 加载场景数据
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static SceneData LoadSceneData(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                SceneData sceneData = new SceneData();

                byte[] buf = new byte[fs.Length];
                fs.Read(buf, 0, buf.Length);

                int off = 0;

                sceneData.SceneMapPath = Tools.BytesToString(buf, 64, true, off); off += 64;
                sceneData.OpenFlag = buf[off]; off++;


                //事件
                short num = Tools.BytesToShort(buf, off); off += 2;
                for (int i = 0; i < num; i++)
                {
                    SceneNPC npc = new SceneNPC();
                    npc.EventType = buf[off]; off++;        //事件类型
                    npc.X = Tools.BytesToShort(buf, off); off += 2; //X
                    npc.Y = Tools.BytesToShort(buf, off); off += 2; //Y

                    byte en = buf[off]; off++;  //人物事件
                    for (int n = 0; n < en; n++)
                    {
                        SceneEvent se = new SceneEvent();
                        se.ID = Tools.BytesToString(buf, 64, true, off); off += 64;
                        se.Priority = buf[off]; off++;

                        npc.EventList.Add(se);
                    }


                    npc.EID = Tools.BytesToShort(buf, off); off += 2; //事件者编号
                    npc.Direction = buf[off]; off++;        //方向
                    npc.Voice = Tools.BytesToShort(buf, off); off += 2; //对话音效

                    Point p = new Point(npc.X, npc.Y);
                    sceneData.SceneNPCList[p] = npc;
                }

                //跳转场景
                short jnum = Tools.BytesToShort(buf, off); off += 2;
                for (int i = 0; i < jnum; i++)
                {
                    SceneJump jump = new SceneJump();
                    jump.X = Tools.BytesToShort(buf, off); off += 2; //X
                    jump.Y = Tools.BytesToShort(buf, off); off += 2; //Y
                    jump.SceneID = Tools.BytesToString(buf, 32, true, off); off += 32;  //跳转场景编号
                    jump.ToX = Tools.BytesToShort(buf, off); off += 2; //TOX
                    jump.ToY = Tools.BytesToShort(buf, off); off += 2; //TOY

                    Point p = new Point(jump.X, jump.Y);
                    sceneData.SceneJumpList[p] = jump;

                }

                return sceneData;
            }
        }
    }
}
